package hyl.core.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @className: ReflectionUtil
 * @description: 反射工具类
 * @author: dayou
 * @date: 2018年8月5日
 */
public class MyReflect {
	private static final Logger log = LoggerFactory.getLogger(MyReflect.class);
	private Class<?> _ownerClass = null;
	private Object _owner;

	// public MyReflect getClass(String className) throws ClassNotFoundException {
	// _ownerClass = Class.forName(className);
	// return this;
	// }
	public MyReflect(Object owner) {
		_ownerClass = owner.getClass();
		_owner = owner;
	}

	public MyReflect(Object owner, Class<?> clazz) {
		_ownerClass = clazz;
		_owner = owner;
	}

	/**
	 * @title: setField
	 * @description: 设置某个属性值
	 * @param owner
	 * @param fieldName
	 * @param value
	 * @throws Exception
	 * @return: void
	 */
	public void setField(String fieldName, Object value) throws Exception {
		Field field = _ownerClass.getDeclaredField(fieldName);
		field.setAccessible(true);
		field.set(_owner, value);
	}

	/**
	 * @title: setFieldAll
	 * @description: 设置父类的field的值
	 * @param owner
	 * @param fieldName
	 * @param value
	 * @throws Exception
	 * @return: void
	 */
	public void setSuperField(String fieldName, Object value) throws Exception {
		Field field = null;
		for (Class<?> clazz = _ownerClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				field = clazz.getDeclaredField(fieldName);
				// log.info(field + " find : in " + clazz.getName());
				break;
			} catch (Exception e) {
				log.error(fieldName + " not find in " + clazz.getName());
			}
		}
		field.setAccessible(true);
		field.set(_owner, value);
	}

	/**
	 * 得到某个对象的公共属性
	 * 
	 * @param owner , fieldName
	 * @return 该属性对象
	 * @throws Exception
	 */
	public Object getField(String fieldName) throws Exception {
		Field field = _ownerClass.getField(fieldName);
		Object property = field.get(_owner);
		return property;
	}

	// class.getMethods()
	// class.getDeclaredFields()
	/**
	 * 执行某对象方法
	 * 
	 * @param owner      对象
	 * @param methodName 方法名
	 * @param args       参数
	 * @return 方法返回值
	 * @throws Exception
	 */
	public Object invoke(String methodName, Object[] args) throws Exception {
		Method method;
		Class<?>[] argsClass = getArgClasss(args);
		if (argsClass == null) {
			method = _ownerClass.getDeclaredMethod(methodName);
			return method.invoke(_owner);
		} else {
			method = _ownerClass.getDeclaredMethod(methodName, argsClass);
			method.setAccessible(true);
			return method.invoke(_owner, args);
		}
	}

	/**
	 * @title: invokeMethodAll
	 * @description: 调用所有的函数, 包括父类的所有函数
	 * @param methodName 函数名称
	 * @param args       根据参数识别参数类型
	 * @return
	 * @throws Exception
	 * @return: Object
	 */
	public Object invokeMethodAll(String methodName, Object... args) throws Exception {
		Class<?>[] argsClass = getArgClasss(args);
		Method method = getDeclaredAllMethod(methodName, argsClass);
		if (method == null)
			return null;
		method.setAccessible(true);
		if (argsClass == null)
			return method.invoke(_owner);
		else
			return method.invoke(_owner, args);
	}

	/**
	 * 是不是某个类的实例
	 * 
	 * @param obj 实例
	 * @param cls 类
	 * @return 如果 obj 是此类的实例，则返回 true
	 */
	public boolean isInstance(Class<?> cls) {
		return cls.isInstance(_owner);
	}

	/**
	 * @title: getDeclaredMethod @description: *
	 *         1.调用getMethods方法输出的是自身的public方法和父类Object的public方法。
	 *         调用getDeclaredMethods方法输出的是自身的public、protected、private方法。
	 *         2.如果想获取父类的私有函数 @param object @param methodName @param
	 *         parameterTypes @return Method @throws
	 */
	public Method getDeclaredAllMethod(String methodName, Class<?>... parameterTypes) {
		Method method = null;
		for (Class<?> clazz = _ownerClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				method = clazz.getDeclaredMethod(methodName, parameterTypes);
				return method;
			} catch (Exception e) {
			}
		}
		return null;
	}

	public Method getDeclaredMethod(String methodName, Class<?>... parameterTypes) {
		try {
			Method method = _ownerClass.getDeclaredMethod(methodName, parameterTypes);
			return method;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 返回函数参数的类型
	 * 
	 * @param args
	 * @return
	 */
	public static Class<?>[] getArgClasss(Object[] args) {
		Class<?>[] argsClass = null;
		if (args == null || args.length == 0) {
			return null;
		}
		argsClass = new Class[args.length];
		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
			// if (args[i].getClass() == Integer.class) { // 一般的函数都是 int 而不是Integer
			// argsClass[i] = int.class;
			// } else if (args[i].getClass() == Float.class) { // 一般的函数都是 int 而不是Integer
			// argsClass[i] = float.class;
			// } else if (args[i].getClass() == Double.class) { // 一般的函数都是 int 而不是Integer
			// argsClass[i] = double.class;
			// } else {
			// argsClass[i] = args[i].getClass();
			// }
		}
		return argsClass;
	}
}